// 文件名：array_ring_buffer.cpp
// 目的：实现一个固定容量、基于数组的无锁环形缓冲区（单生产者/单消费者语义未强制，但无并发保护）。
// 核心概念：
//   - 使用定长 std::array<T, N> 作为底层存储；
//   - 通过 read_ 与 write_ 两个指针（索引）配合 size_ 计数，支持循环写/读；
//   - push：当缓冲区未满时写入元素，并前移写指针（模 N）；
//   - pop：当缓冲区非空时读出元素，并前移读指针（模 N）；
//   - 提供 size()/full()/empty() 查询状态。
// 复杂度：
//   - push/pop/查询：O(1)。
// 边界与注意：
//   - 满时 push 返回 false（不覆盖旧数据）；可扩展为“覆盖写”策略（覆盖最旧元素）；
//   - 返回值：pop 使用 std::optional<T> 表示可能无元素可取；
//   - 并发：未加锁；多线程需添加同步或使用无锁环形队列算法（需原子操作与内存序）。
//   - T 的要求：可移动构造（用于高效转移元素）。

#include <array>
#include <iostream>
#include <optional>

template <typename T, std::size_t N>
class RingBuffer {
public:
    // 入队：缓冲未满则写入，返回 true；已满则拒绝写入并返回 false
    bool push(T value) {
        if (size_ == N) return false;              // 缓冲区已满
        buffer_[write_] = std::move(value);        // 写入当前位置
        write_ = (write_ + 1) % N;                 // 写指针前移（环绕）
        ++size_;                                   // 元素计数 +1
        return true;
    }

    // 出队：缓冲非空则取出头元素并返回，否则返回 std::nullopt
    std::optional<T> pop() {
        if (size_ == 0) return std::nullopt;       // 缓冲区为空
        T value = std::move(buffer_[read_]);       // 取出当前位置
        read_ = (read_ + 1) % N;                   // 读指针前移（环绕）
        --size_;                                   // 元素计数 -1
        return value;
    }

    // 状态查询
    std::size_t size() const { return size_; }
    bool full() const { return size_ == N; }
    bool empty() const { return size_ == 0; }

private:
    std::array<T, N> buffer_{}; // 固定容量的底层存储
    std::size_t write_ = 0;     // 下一个写入位置
    std::size_t read_ = 0;      // 下一个读取位置
    std::size_t size_ = 0;      // 当前元素数
};

int main() {
    RingBuffer<int, 4> rb;
    for (int i = 1; i <= 5; ++i) {
        if (rb.push(i)) {
            std::cout << "Pushed " << i << '\n';
        } else {
            std::cout << "Buffer full, dropping " << i << '\n';
        }
    }

    while (!rb.empty()) {
        std::cout << "Popped " << *rb.pop() << '\n';
    }
    return 0;
}